#include "rtsp.h"
#include <iostream>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/prctl.h>
#include <string.h>
#include <algorithm>

Rtsp::Rtsp() : port(0), addr(""), sockfd(-1) {
    // 默认构造函数，初始化成员变量
}

Rtsp::~Rtsp() {
    // 析构函数，关闭socket
    if (sockfd != -1) {
        close(sockfd);
    }
}

int Rtsp::init(int port, const std::string& addr) {
    this->port = port;
    this->addr = addr;

    // 打印初始化信息
    std::cout << "Rtsp initialized with port: " << port << " and address: " << addr << std::endl;

    // 调用TCP初始化
    if (tcp_init() != 0) {
        return -1;  // TCP初始化失败
    }

    // 返回成功状态码
    return 0;
}

int Rtsp::tcp_init() {
    // 创建socket
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        std::cerr << "Failed to create socket" << std::endl;
        return -1;
    }

    // 设置服务器地址结构
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    if (inet_pton(AF_INET, addr.c_str(), &server_addr.sin_addr) <= 0) {
        std::cerr << "Invalid address or address not supported" << std::endl;
        close(sockfd);
        return -1;
    }

    // 绑定socket到地址
    if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        std::cerr << "Bind failed" << std::endl;
        close(sockfd);
        return -1;
    }

    // 开始监听
    if (listen(sockfd, 3) < 0) {
        std::cerr << "Listen failed" << std::endl;
        close(sockfd);
        return -1;
    }

    std::cout << "TCP server listening on " << addr << ":" << port << std::endl;
    return 0;
}

int Rtsp::get_sockfd() {
    return sockfd;
}

RtspProtocol* RtspProtocol::instance = nullptr;

RtspProtocol* RtspProtocol::get_instance()
{
    if (instance == nullptr) {
        instance = new RtspProtocol();
    }
    return instance;
}


int RtspProtocol::add_sockfd(int fd)
{
    sockfd.push_back(fd);

    return 0;
}

int RtspProtocol::add_tcp_server_fd(int fd)
{
    tcp_server_fd.push_back(fd);

    return 0;
}


std::string RtspProtocol::get_local_ip(int sockfd) 
{
    sockaddr_in addr;
    socklen_t addr_len = sizeof(addr);
    if (getsockname(sockfd, (sockaddr*)&addr, &addr_len) == 0) {
        char ip[INET_ADDRSTRLEN];
        inet_ntop(AF_INET, &addr.sin_addr, ip, INET_ADDRSTRLEN);
        return std::string(ip);
    }
    return "127.0.0.1"; // 默认回退到 localhost
}


std::string RtspProtocol::option_request_deal(int sockfd, int seq)
{
    std::ostringstream oss;
    oss << "RTSP/1.0 200 OK\r\n"
        << "CSeq: " << seq << "\r\n"
        << "Public: OPTIONS, DESCRIBE, SETUP, PLAY\r\n"
        << "\r\n";

    return oss.str();
}

std::string RtspProtocol::describe_request_deal(int sockfd, int seq) 
{
    /* 获取本地 IP */
    std::string urlStr(get_local_ip(sockfd));
    size_t ipStart = urlStr.find("rtsp://") + strlen("rtsp://");
    size_t ipEnd = urlStr.find(':', ipStart);
    if (ipEnd == std::string::npos) {
        ipEnd = urlStr.find('/', ipStart); // 如果没有找到端口号，则查找路径开始位置
    }
    std::string localIpStr = urlStr.substr(ipStart, ipEnd - ipStart);

    // 定义 SDP 格式字符串
    const std::string sdpFormat = 
        "v=0\r\n"
        "o=- 9%ld 1 IN IP4 %s\r\n"
        "t=0 0\r\n"
        "a=control:*\r\n"
        "m=video 0 RTP/AVP 96\r\n"
        "a=rtpmap:96 H264/90000\r\n"
        "a=control:track0\r\n";

    // 使用 ostringstream 构建 SDP
    std::ostringstream sdpStream;
    sdpStream << "v=0\r\n"
              << "o=- 9" << time(NULL) << " 1 IN IP4 " << localIpStr << "\r\n"
              << "t=0 0\r\n"
              << "a=control:*\r\n"
              << "m=video 0 RTP/AVP 96\r\n"
              << "a=rtpmap:96 H264/90000\r\n"
              << "a=control:track0\r\n";
    std::string sdpStr = sdpStream.str();

    // 定义 RTSP 响应格式字符串
    const std::string rtspResponseFormat = 
        "RTSP/1.0 200 OK\r\nCSeq: %d\r\n"
        "Content-Base: %s\r\n"
        "Content-type: application/sdp\r\n"
        "Content-length: %d\r\n\r\n"
        "%s";

    // 使用 ostringstream 构建 RTSP 响应
    std::ostringstream resultStream;
    resultStream << "RTSP/1.0 200 OK\r\nCSeq: " << seq << "\r\n"
                 << "Content-Base: " << localIpStr << "\r\n"
                 << "Content-type: application/sdp\r\n"
                 << "Content-length: " << sdpStr.size() << "\r\n\r\n"
                 << sdpStr;

    return resultStream.str();
}

std::string RtspProtocol::setup_request_deal(int sockfd, int seq) 
{
    return "RTSP/1.0 200 OK\r\n";
}
std::string RtspProtocol::play_request_deal(int sockfd, int seq)
{ 
    return "RTSP/1.0 200 OK\r\n";
}

std::string RtspProtocol::request_deal(int sockfd, int seq, std::string method)
{
    if (method == "OPTIONS") {
        return option_request_deal(sockfd, seq);
    } else if (method == "SETUP") {
        return setup_request_deal(sockfd, seq);
    } else if (method == "DESCRIBE") {
        return describe_request_deal(sockfd, seq);
    } else if (method == "PLAY") {
        return play_request_deal(sockfd, seq);
    } else {
        std::cout << "Unsupported method: " << method << std::endl;
        return "";
    }
}

std::string trim(const std::string& s) {
    auto start = s.begin();
    while (start != s.end() && std::isspace(*start)) ++start;

    auto end = s.end();
    do {
        --end;
    } while (std::distance(start, end) > 0 && std::isspace(*end));

    return std::string(start, end + 1);
}

bool RtspProtocol::parse_rtsp_request(const std::string& request, RtspRequest& out) 
{
    std::istringstream stream(request);
    std::string line;

    // 解析第一行（方法、URI、版本）
    if (std::getline(stream, line)) {
        line = trim(line);
        std::istringstream firstLine(line);
        firstLine >> out.method >> out.uri >> out.version;
    }

    // 解析后续行
    while (std::getline(stream, line)) {
        std::string trimmedLine = trim(line);
        if (trimmedLine.rfind("CSeq: ", 0) == 0) {
            std::istringstream lineStream(trimmedLine);
            std::string key;
            lineStream >> key >> out.cseq;
            break;
        }
    }

    return !out.method.empty() && !out.uri.empty();
}

int RtspProtocol::parser(int fd)
{
    int ret = 0;

    char read_buf[1024] = {0};

    ret = read(fd, &read_buf, sizeof(read_buf));
    std::string str_data(read_buf);
    std::string reply;
    RtspRequest req;

    // 优化日志输出逻辑，避免频繁打印相同的日志信息
    if (ret > 0) {
        std::cout << "Received data from fd " << fd << ": \n" << read_buf << std::endl;

        int ret = parse_rtsp_request(read_buf, req);
        if(ret == 1) {
            std::cout << "Method: " << req.method << ", URI: " << req.uri << ", Seq: " << req.cseq << std::endl;
            reply = request_deal(fd, req.cseq, req.method);
            std::cout << "Reply: \n" << reply << std::endl;
            write(fd, reply.c_str(), reply.size());
        } else {
            std::cout << "Failed to parse RTSP request." << std::endl;
        }
    } else if (ret == 0) {
        std::cout << "Connection closed by fd " << fd << std::endl;
        close(fd);
        sockfd.erase(
            std::remove(sockfd.begin(), sockfd.end(), fd),
            sockfd.end()
        );
    } else {
        // 仅在 errno 不为 EAGAIN 或 EWOULDBLOCK 时打印错误日志
        if (errno != EAGAIN && errno != EWOULDBLOCK) {
            std::cerr << "Error reading from fd " << fd << ": " << strerror(errno) << std::endl;
            close(fd);
            sockfd.erase(
                std::remove(sockfd.begin(), sockfd.end(), fd),
                sockfd.end()
            );
        }
    }

    return ret;
}

void* RtspProtocol::process(void* arg)
{
    fd_set fdsr;
    int ret = 0;

    prctl(PR_SET_NAME, "rtsp_protocol");
    pthread_detach(pthread_self());

    struct timeval initial_timeout = {1, 0};

    while (1) { 
        usleep(10 * 1000);

        int max_fd = -1;

        for(int i = 0; i < tcp_server_fd.size(); i++) {
            FD_SET(tcp_server_fd[i], &fdsr);
            if (tcp_server_fd[i] > max_fd) max_fd = tcp_server_fd[i];
        }

        for(int i = 0; i < sockfd.size(); i++) {
            FD_SET(sockfd[i], &fdsr);
            if (sockfd[i] > max_fd) max_fd = sockfd[i];
        }

        if(max_fd == -1) {
            std::cout << "no fd" << std::endl;
            continue;
        }

        struct timeval timeout = initial_timeout;
        ret = select(max_fd + 1, &fdsr, NULL, NULL, &timeout);

        if (ret < 0) {
            std::cout << "select error" << std::endl;
            continue;
        } else if (ret == 0) {
            std::cout << "select timeout" << std::endl;
            continue;
        }

        for(int i = 0; i <tcp_server_fd.size(); i++) {
            if (FD_ISSET(tcp_server_fd[i], &fdsr)) { // 检查是否是监听 socket 可读
                struct sockaddr_in client_addr;
                socklen_t addr_len = sizeof(client_addr);
                int client_fd = accept(tcp_server_fd[i], (struct sockaddr*)&client_addr, &addr_len);
                if (client_fd >= 0) {
                    sockfd.push_back(client_fd); // 将新连接加入监听列表
                    std::cout << "New connection accepted" << std::endl;
                }
            }
        }

        for(int i = 0; i < sockfd.size(); i++) {
            if (FD_ISSET(sockfd[i], &fdsr)) {
                parser(sockfd[i]);
            }
        }
    }

    return NULL;
}

static void* process_proxy(void* arg) {
    RtspProtocol *rtsp_protocol = RtspProtocol::get_instance();
    return rtsp_protocol->process(nullptr);
}

int RtspProtocol::start()
{
    int ret = 0;
    ret = pthread_create(&thread_id, nullptr, process_proxy, nullptr);

    return ret;
}

int RtspProtocol::stop()
{
    int ret = 0;

    return ret;
}

RtspProtocol::RtspProtocol()
{
    timeout.tv_sec = 1;
    timeout.tv_usec = 0;
}

RtspProtocol::~RtspProtocol()
{

}